﻿#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <iostream>
#include <math.h>
#include <corecrt_wstdio.h>

using namespace std;

#define BLOCK_SIZE 40
#define ROW_NUM 13
#define COL_NUM 21
#define COLOR_TYPE_NUM 9

struct Block
{
	int x; //方块的像素坐标。
	int y; //方块的像素坐标。
	int i;
	int j;
	int color_ID;
};

void draw_block_hint(int i, int j, COLORREF color, int fill);
void startup();
void show();
void update_without_input();
void update_with_input();

Block blocks[ROW_NUM][COL_NUM];
COLORREF colors[COLOR_TYPE_NUM + 1];
float max_time = 0.0f;
float remain_time = 0.0f;
float punish_time = 0.0f;
int score = 0;
int no_zero_block_num = 0;
int level = 1;


int main()
{
	startup();
	while (!(_kbhit() && _getch() == 'q') && level != 9)
	{
		show();
		update_without_input();
		update_with_input();

		/*if (level == 9)
		{
			break;
		}*/
	}
	return 0;
}


void startup()
{
	int width = BLOCK_SIZE * COL_NUM;
	int height = BLOCK_SIZE * ROW_NUM;
	initgraph(width, height);
	setbkcolor(RGB(220, 220, 220));
	setfillcolor(RED);
	setlinestyle(PS_SOLID, 2);
	cleardevice();

	BeginBatchDraw();

	srand(time(0));

	max_time = 300 - level * 10;
	remain_time = max_time;
	punish_time = 0;

	colors[0] = RGB(220, 220, 220);

	for (int i = 1; i < COLOR_TYPE_NUM; i++)
	{
		colors[i] = HSVtoRGB((i - 1) * 40, 0.6, 0.8);
	}

	no_zero_block_num = 0;

	for (int i = 0; i < ROW_NUM - 1; i++)
	{
		for (int j = 0; j < COL_NUM; j++)
		{
			int t = rand() % (int(COLOR_TYPE_NUM * 1.5));

			if (t < COLOR_TYPE_NUM + 1)
			{
				blocks[i][j].color_ID = t;
			}
			else
			{
				blocks[i][j].color_ID = 0;
			}

			blocks[i][j].x = j * BLOCK_SIZE;
			blocks[i][j].y = i * BLOCK_SIZE;
			blocks[i][j].i = i;
			blocks[i][j].j = j;

			if (blocks[i][j].color_ID != 0)
			{
				no_zero_block_num++;
			}
		}
	}
	score = 0;
}


void show()
{
	cleardevice();

	//画棋盘。
	setlinecolor(WHITE);
	for (int i = 0; i < ROW_NUM; i++)
	{
		for (int j = 0; j < COL_NUM; j++)
		{
			setfillcolor(colors[blocks[i][j].color_ID]);
			fillrectangle(blocks[i][j].x, blocks[i][j].y, blocks[i][j].x + BLOCK_SIZE, blocks[i][j].y + BLOCK_SIZE);
		}
	}

	//画血条。
	setlinecolor(RED);
	setfillcolor(RED);
	fillrectangle(0, BLOCK_SIZE * (ROW_NUM - 0.9), remain_time * BLOCK_SIZE * COL_NUM / max_time, BLOCK_SIZE * (ROW_NUM + 0.8));

	//画提示文字。
	TCHAR text[80];
	setbkmode(TRANSPARENT);
	settextcolor(WHITE);
	settextstyle(22, 0, _T("楷体"));
	swprintf_s(text, _T("当前第%d关，已得%d分，达到%d分进入下一关"), level, score, int(0.9 * no_zero_block_num));
	outtextxy(BLOCK_SIZE * (COL_NUM / 3 - 0.1), BLOCK_SIZE * (ROW_NUM - 0.8), text);

	if (score >= 0.9 * no_zero_block_num)
	{
		settextstyle(130, 0, _T("楷体"));
		outtextxy(BLOCK_SIZE * (COL_NUM / 6.0), BLOCK_SIZE * (ROW_NUM / 3.0), _T("游戏胜利!"));
		Sleep(100);
	}

	FlushBatchDraw();
}


void update_without_input()
{
	static clock_t start = clock();
	clock_t now = clock();
	double duration = double(now - start) / CLOCKS_PER_SEC;
	remain_time = max_time - duration - punish_time;

	if (score >= int(0.9 * no_zero_block_num))
	{
		level++;
		start = clock();
		startup();
	}
	else if (remain_time <= 0)
	{
		start = clock();
		startup();
	}
}


void update_with_input()
{
	if (remain_time <= 0)
	{
		return;
	}

	MOUSEMSG m;

	if (MouseHit())
	{
		m = GetMouseMsg();
		if (m.uMsg == WM_LBUTTONDOWN)
		{
			int clicked_i = int(m.y) / BLOCK_SIZE;
			int clicked_j = int(m.x) / BLOCK_SIZE;

			if (blocks[clicked_i][clicked_j].color_ID != 0)
			{
				return;
			}

			show();

			draw_block_hint(clicked_i, clicked_j, RGB(100, 100, 100), 1);

			Block four_blocks[4] = { blocks[clicked_i][clicked_j] };

			for (int up = 0; clicked_i - up >= 0; up++)
			{
				if (blocks[clicked_i - up][clicked_j].color_ID != 0)
				{
					four_blocks[0] = blocks[clicked_i - up][clicked_j];
					break;
				}
			}
			for (int down = 0; clicked_i + down < ROW_NUM; down++)
			{
				if (blocks[clicked_i + down][clicked_j].color_ID != 0)
				{
					four_blocks[1] = blocks[clicked_i + down][clicked_j];
					break;
				}
			}
			for (int left = 0; clicked_j - left >= 0; left++)
			{
				if (blocks[clicked_i][clicked_j - left].color_ID != 0)
				{
					four_blocks[2] = blocks[clicked_i][clicked_j - left];
					break;
				}
			}
			for (int right = 0; clicked_j + right < COL_NUM; right++)
			{
				if (blocks[clicked_i][clicked_j + right].color_ID != 0)
				{
					four_blocks[3] = blocks[clicked_i][clicked_j + right];
					break;
				}
			}
			int color_statistics[COLOR_TYPE_NUM + 1] = { 0 };
			int bad_click = 1;

			for (int i = 0; i <= COLOR_TYPE_NUM; i++)
			{
				//遍历four_blocks。
				for (int j = 0; j < 4; j++)
				{
					if (four_blocks[j].color_ID == i)
					{
						color_statistics[i]++;
					}
				}
				//消除方块。
				if (color_statistics[i] >= 2)
				{
					bad_click = 0;
					//将已消除的方块变为灰白色。
					for (int j = 0; j < 4; j++)
					{
						if (four_blocks[j].color_ID == i)
						{
							draw_block_hint(four_blocks[j].i, four_blocks[j].j, BLACK, 0);
							blocks[four_blocks[j].i][four_blocks[j].j].color_ID = 0;
						}
					}
					score += color_statistics[i];
				}
			}
			//点错方块则减少时间。
			if (bad_click == 1)
			{
				punish_time += 10;
			}

			FlushBatchDraw();
			Sleep(300);
		}
	}
}


void draw_block_hint(int i, int j, COLORREF color, int fill)
{
	setlinecolor(color);
	setfillcolor(color);
	if (fill == 1)
	{
		fillrectangle(blocks[i][j].x, blocks[i][j].y, blocks[i][j].x + BLOCK_SIZE, blocks[i][j].y + BLOCK_SIZE);
	}
	if (fill == 0)
	{
		rectangle(blocks[i][j].x, blocks[i][j].y, blocks[i][j].x + BLOCK_SIZE, blocks[i][j].y + BLOCK_SIZE);
	}
}